<template>
	<GenericModal
		id="passwordModal"
		ref="modal"
		:title="title"
		data-testid="password-modal"
		:uncloseable="!updateMode"
		@open="open"
		@closed="closed"
	>
		<p v-if="error" class="text-danger">{{ $t("passwordModal.error") }} "{{ error.trim() }}"</p>
		<p v-if="!updateMode" class="mb-4">{{ $t("passwordModal.description") }}</p>
		<form
			v-if="modalVisible"
			ref="form"
			:class="{ 'was-validated': showValidation }"
			novalidate
			@submit="setPassword"
		>
			<!-- password manager hint -->
			<input
				id="username"
				class="d-none"
				type="text"
				name="username"
				autocomplete="username"
				value="admin"
			/>
			<FormRow
				v-if="updateMode"
				id="passwordCurrent"
				:label="$t('passwordModal.labelCurrent')"
			>
				<input
					id="passwordCurrent"
					v-model="passwordCurrent"
					type="password"
					class="form-control"
					autocomplete="current-password"
				/>
			</FormRow>
			<FormRow id="passwordNew" :label="$t('passwordModal.labelNew')">
				<input
					id="passwordNew"
					v-model="passwordNew"
					type="password"
					class="form-control"
					autocomplete="new-password"
					required
				/>
				<div class="invalid-feedback">
					{{ $t("passwordModal.empty") }}
				</div>
			</FormRow>
			<FormRow id="passwordRepeat" :label="$t('passwordModal.labelRepeat')">
				<input
					id="passwordRepeat"
					ref="passwordRepeat"
					v-model="passwordRepeat"
					type="password"
					class="form-control"
					autocomplete="new-password"
				/>
				<div v-if="!passwordsMatch" class="invalid-feedback">
					{{ $t("passwordModal.noMatch") }}
				</div>
			</FormRow>

			<div class="d-flex justify-content-end">
				<button
					type="submit"
					class="btn btn-primary justify-self-right"
					:disabled="loading"
				>
					<span
						v-if="loading"
						class="spinner-border spinner-border-sm"
						role="status"
						aria-hidden="true"
					></span>
					{{ submitText }}
				</button>
			</div>
		</form>
	</GenericModal>
</template>

<script>
import GenericModal from "./GenericModal.vue";
import FormRow from "./FormRow.vue";
import api from "../api";
import { updateAuthStatus, isConfigured } from "../auth";

export default {
	name: "PasswordModal",
	components: { FormRow, GenericModal },
	data: () => {
		return {
			modalVisible: false,
			passwordCurrent: "",
			passwordNew: "",
			passwordRepeat: "",
			showValidation: false,
			loading: false,
			error: false,
		};
	},
	computed: {
		passwordsMatch: function () {
			return this.passwordNew === this.passwordRepeat;
		},
		passwordEmpty: function () {
			return this.passwordNew.length === 0;
		},
		updateMode: function () {
			return isConfigured();
		},
		title: function () {
			return this.updateMode
				? this.$t("passwordModal.titleUpdate")
				: this.$t("passwordModal.titleNew");
		},
		submitText: function () {
			return this.updateMode
				? this.$t("passwordModal.updatePassword")
				: this.$t("passwordModal.newPassword");
		},
	},
	methods: {
		open: function () {
			this.modalVisible = true;
		},
		closed: function () {
			this.modalVisible = false;
			this.passwordCurrent = "";
			this.passwordNew = "";
			this.passwordRepeat = "";
			this.error = false;
			this.loading = false;
			this.showValidation = false;
		},
		setPassword: async function (e) {
			this.$refs.passwordRepeat.setCustomValidity(
				this.passwordsMatch && !this.passwordEmpty ? "" : "invalid"
			);

			e.preventDefault();
			e.stopPropagation();
			this.showValidation = true;

			if (this.$refs.form.checkValidity()) {
				await this.savePassword();
				await updateAuthStatus();
			}
		},
		savePassword: async function () {
			this.loading = true;
			this.error = null;
			try {
				const data = {
					current: this.passwordCurrent,
					new: this.passwordNew,
				};
				await api.put("/auth/password", data);
				this.loading = false;
				this.$refs.modal?.close();
			} catch (error) {
				console.error(error);
				this.error = error.response.data;
				this.showValidation = false;
			} finally {
				this.loading = false;
			}
		},
	},
};
</script>
